#ifndef _BOOTLOADER_H_
#define _BOOTLOADER_H_

#include <sys_config.h>
#include <sys_parameters.h>
#include <api/libc/printf.h>
#include <api/libc/string.h>
#include <api/libchunk/chunk.h>
#include <bus/flash/flash.h>
#include <bus/sci/sci.h>
#include <hal/hal_mem.h>
#include <hld/smc/smc.h>
#include <api/libloader/ld_boot_info.h>
#include <api/librsa/flash_cipher.h>
#include <api/librsa/rsa_verify.h>
#include <hld/sec_boot/sec_boot.h>
#include <hld/dsc/dsc.h>
#include <bus/nand/ali_nand.h>

//======================================================//
/*add for pmu standby in bootloader*/
#ifdef _PMU_STANDBY_ENABLE_
#include "ali_pmu_bin.h"
#endif

#define PMU_BASE    0xb805E000	
#define EXIT_STANDBY_STATUS 0x06
#define GET_BYTE(base_add)				(*(volatile UINT8*)(base_add))
//======================================================//

#ifdef FIXED_PRINTF
#undef FIXED_PRINTF
#endif
//#define FIXED_PRINTF(...)     do{}while(0)
#define FIXED_PRINTF     libc_printf

#define PRINTF_BOOTLOGO(a,b)    FIXED_PRINTF("The "#a" = 0x%08x,The "#b" = 0x%08x\n",(UINT32)(a),(UINT32)(b))


#ifdef __mips16
#define SDBBP()		asm volatile(".half 0xe801; \
								  nop")
#else
#define SDBBP()		asm volatile(".word	0x7000003f; \
								  nop");
#endif


extern UINT8  g_crc_bad ;
extern UINT32 unzip_length;

extern struct sto_device *flash_dev ;

extern UINT8 *g_see_unziped   ;

extern UINT32 g_ota_offset ;

extern UINT32 g_boot_type ;

struct pan_device *panel_dev;

#define US_TICKS        (SYS_CPU_CLOCK / 2000000)
#define WAIT_300MS      (300000 * US_TICKS)
#define LOGO_DELAY      (3000000 * US_TICKS)

#define SECTOR_OFFSET_BIT 16
#define FLASH_SECTOR_SIZE (64*1024)
#define HW_SET_GPIO 0x104

/* Calcuate InternalBufferSize for 7-zip */
#define LZMA_BASE_SIZE  1846
#define LZMA_LIT_SIZE   768
#define BUFFER_SIZE     ((LZMA_BASE_SIZE + (LZMA_LIT_SIZE << (0 + 2))) * sizeof(UINT16))

#define OTA_SEE_CODE  3
#define OTA_CPU_CODE  2
#define SEE_CODE  1
#define MAIN_CODE 0
#ifndef LINUX_BOOTLOADER
    #define MAIN_ENTRY 0x80000200
#else
    #define MAIN_ENTRY 0x85000000
#endif
#define C_SECTOR_SIZE 0x10000

//#define USE_SMC1
#define JTAG_KEY_SIZE  256
UINT8 g_jtag_key[JTAG_KEY_SIZE];

#define CFG_KEY_LEN      (0x2000)  // reversed for sig key 

extern int un7zip ( UINT8 *, UINT8 *, UINT8 * );
extern UINT32 g_see_entry;
extern UINT32 g_see_length;
extern UINT32 g_see_ram_base;

typedef enum
{
	SHOW_BANK =0,
	SHOW_OFF,
	SHOW_TIME
}PANNEL_SHOW_TYPE;

struct state_machine_t{
    unsigned int b_boot_status;
    unsigned int b_lowlevel_status;
    unsigned int b_application_status;
    unsigned int b_bootloader_upgrade;
    unsigned int b_lowlevel_upgrade;
    unsigned int b_application_upgrade;
    unsigned int b_bootloader_run_cnt;
    unsigned int b_lowlevel_run_cnt;
    unsigned int b_application_run_cnt;
    unsigned int b_reserved1;
    unsigned int b_reserved2;

    //for expand
    unsigned int b_need_upgrade;
    unsigned int b_backup_exist;
    unsigned int b_lowlevel_backup_exist;
    unsigned int b_boot_backup_exist;
    unsigned int b_nor_upgrade;
    unsigned int b_nor_reserved;
    unsigned int b_nor_reserved_upgrade;
    unsigned int b_nand_reserved;
    unsigned int b_nand_reserved_upgrade;
    unsigned int b_nand_whole_upgrade;
    unsigned int b_cur_uboot;
    unsigned int b_reserved[4];
};

#define UPG_DESC_BOOT_RUN_NONE	        0x03
#define UPG_DESC_BOOT_RUN_ENTER	        0x00
#define UPG_DESC_BOOT_RUN_START	        0x01
#define UPG_DESC_BOOT_RUN_OVER	        0x02

#define UPG_DESC_BOOT_UPG_NONE	        0x07
#define UPG_DESC_BOOT_UPG_NO		    0x00
#define UPG_DESC_BOOT_UPG_START	        0x01
#define UPG_DESC_BOOT_UPG_OVER	        0x02
#define UPG_DESC_BOOT_UPG_RUN	        0x03

#define UPG_DESC_UBOOT1                 0x00
#define UPG_DESC_UBOOT2                 0x01

void stop_watchdog();
UINT8 check_program(void);
void bl_init_uart();
void bl_init_flash();
RET_CODE bl_get_chunk_len(UINT32 id, UINT32 *addr, UINT32 *len);
int api_load_data_from_nandflash(unsigned long addr, unsigned long len, UINT8 * buf);
void api_store_key_to_nandflash(UINT32 id);

#ifdef _HW_SECURITY_ENABLE_
void set_uboot_config(UINT32 uboot_entry);
RET_CODE bl_prepare_key(struct UKEY_INFO *ukey);
RET_CODE flush_ukey(struct UKEY_INFO *ukey);
#endif

#endif
